package chapter3;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner; // 要使用的类不属于基本java.lang包时，必须要手动import
import java.util.Arrays;
import java.math.*;
// import java.util.*

// /** */这种注释用来生成文档
/**
 * Main
 */
public class Main {
    // Java中，任何函数都必须是类的方法；Java也没有像C++的范围public，需自己标明访问控制符
    public static void main(String[] args) throws IOException // 因为PrintWriter而添加了throws IOException，会在后面介绍
    {
        // main必须是公有方法和静态成员
        // main没有返回值，除非自己用exit返回，否则都是虚拟机去处理
        System.out.println(MY_NUM);

        // Math类的方法：此处跳过，用时翻书
        // Java提供了预定义类String来表示字符串，这不是基本类型
        String s1 = "abc";
        String s2 = "a" + s1.substring(1,3); // String是不可变类型，修改必须创建副本
        // 用==判断String是比较其指针，会导致随机行为(true or false)
        System.out.printf("%s, %s\n", s1==s2, s1.equals(s2)); // equals方法才是比较内容；%s可格式化任意对象
        if(s1!=null && s1.length()!=0); // 检查s1既不是null也不为空
        // 在null上调方法会报错。不能把数字转换为布尔值（这与C++大不相同）

        s1 = "ice你好"; // java的char采用UTF-16
        System.out.println(s1.charAt(4)); // '好' // 获取第五个代码单元(无关每个字符长度)
        System.out.println(s1.codePointAt(4)); // 22909 // 获取第五个码点
        int [] codePoints = s1.codePoints().toArray(); // 类似golang的rune数组
        s1 = new String(codePoints, 0, codePoints.length);
        // String类的其他方法：与python相近，此处跳过

        StringBuilder builder = new StringBuilder();
        // StringBuffer作用也一样，不过可以用在多线程
        builder.append('a');
        builder.append("bc"); // builder避免了每次追加都得拷贝所有数据
        builder.setCharAt(2, '我'); // 修改第二个代码单元
        // insert, delete不介绍
        s1 = builder.toString();
        System.out.println(s1); // ab我

        if(s1==null){
            Scanner in = new Scanner(System.in); // 构造一个与标准输入流System.in关联的Scanner对象
            s2 = in.next(); // 读取一个单词(到空白字符结束，空白字符仍留在缓冲区)
            var num = in.nextInt(); // 读取一个数字
            s2 = in.nextLine(); // 读取一行(从当前位置开始到换行符)(如果当前就是\n，会读到空)
            in.close();
            System.out.println(s2+" "+ num); // 字符串可与数字直接连接
            // in:"abc 123 def"  out:"def 123" 
            in = new Scanner("可以直接用字符串传给构造器"); in.close();
        }

        PrintWriter out = new PrintWriter("test.txt", StandardCharsets.UTF_8); 
        // 若无此文件则创建，路径相对于启动虚拟机时的目录(执行java命令)
        out.write("hello");
        out.close();
        Scanner in = new Scanner(Path.of("test.txt"), StandardCharsets.UTF_8); // 传入Path对象
        System.out.println(in.nextLine());
        in.close();

        BigInteger b1 = BigInteger.valueOf((long)1e15), b2 = BigInteger.valueOf((long)2e15);
        var b = b1.add(b2); // 只能调方法做运算。java在拼接字符串中只重载了+，没有更多的运算符重载
        System.out.println(b);

        int N = 3; // 数组可在运行时指明长度，但是之后不可变长
        int[] ar = new int[N]; // 整数数组默认均为0
        ar = new int[] {1, 2, 3, 4}; // Java没有分配在栈上的数组，比较类似于在C++中new一个数组
        String[] strs = new String[N]; // 对象数组默认均为null
        gate:
        for(int i=0;i<10;)
        {
            ar[i] = i;
            break gate; // 带标签的break语句
        }
        for(@SuppressWarnings("unused") String s : strs) // for each循环。Java中对数组也可以
        {
            s = ""; // 无法改变strs里的元素。只能用下标for循环去改
        }
        System.out.println(ar.length);
        System.out.println(Arrays.toString(strs)); // [null, null, null] // 用该方法可以免去for循环打印
        Arrays.fill(strs, ""); // 填充数组

        var ar1 = ar; // 只是拷贝了指针
        ar1[1] = 5;
        Arrays.sort(ar1); // 用了快排算法
        ar1 = Arrays.copyOf(ar1, 2* ar1.length); // 使用Arrays.copyOf进行内容拷贝。这里的效果是对ar1扩容
        System.out.println(Arrays.toString(ar1)); // [0, 3, 4, 5, 0, 0, 0, 0]
        System.out.println(Arrays.equals(ar, ar1));
        if(args.length > 0)
            System.out.println(Arrays.toString(args)); // 与C++不同，args[0]不是程序名，而是第一个参数
        // Arrays类的其他方法：都很有用（比如二分查找），自行了解

        int[][] ar2 = {
            {1,2,3},
            {4,5,6}
        };
        System.out.println(Arrays.toString(ar2)); // 会打印一个两元素的一维数组，每个元素指向了一个长度为3的数组
        // java没有真正的多维数组（不记得请翻书）
        
    }
    public static final int MY_NUM = 0; 
    // 1.fianl表示常量(const是一个未用保留字) 2.int占4字节，java中类型与平台无关，且没有无符号类型
}